﻿using Google.Protobuf;
using ServerCommon.Log;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ServerCommon.Net
{
    public abstract class ProtocolParser
    {
        private static readonly LogHelper Log = LogHelper.GetLogger(typeof(ProtocolParser));

        private readonly Func<IMessage> _factory;

        internal ProtocolParser(Func<IMessage> factory)
        {
            _factory = factory;
        }

        public abstract void SetProtocolId(int protocolId);

        public IMessage ParseFrom(byte[] buffer, int offset, int length)
        {
            if (null == buffer)
            {
                Log.Error($"ParseFrom. null == buffer.{this} offset:{offset} length:{length}");
                return null;
            }

            var msg = _factory();
            msg.MergeFrom(buffer, offset, length);
            return msg;
        }

        // 目前使用块数据操作方式，只允许byte[] StringByte方式操作，不支持Stream Span
        public static T Parse<T>(byte[] data) where T : class, IMessage, new()
        {
            if (data is not { Length: > 0 })
            {
                return null;
            }
            T obj;
            try
            {
                obj = new T();
                obj.MergeFrom(data);
            }
            catch (Exception ex)
            {
                obj = null;
                Log.Error($"Parse<T>(byte[] data) error, Type={typeof(T)}, Message={ex.Message}");
            }
            return obj;
        }

        public static T Parse<T>(ByteString data) where T : class, IMessage, new()
        {
            if (data is not { Length: > 0 })
            {
                return null;
            }
            T obj;
            try
            {
                obj = new T();
                obj.MergeFrom(data);
            }
            catch (Exception ex)
            {
                obj = null;
                Log.Error($"Parse<T>(ByteString data) error, Type={typeof(T)}, Message={ex.Message}");
            }
            return obj;
        }

        public static ProtocolParser<T> Create<T>() where T : Pb.Protocol<T>, IMessage<T>, new()
        {
            return new ProtocolParser<T>();
        }
    }

    public class ProtocolParser<T>() : ProtocolParser(() => new T()) where T : Pb.Protocol<T>, IMessage<T>, new()
    {
        public override void SetProtocolId(int protocolId)
        {
            Pb.Protocol<T>.StaticProtocolId = protocolId;
        }
    }
}
